package com.tyj.tuyijieapp.config.security.captcha;


import com.tyj.tuyijieapp.config.security.handler.FailureHandler;
import com.tyj.tuyijieapp.config.security.handler.SuccessHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * <p></p>
 *
 * @author lhf
 * @since 2020/6/6
 */
@Component
public class CaptchaAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {
    private static Logger log = LoggerFactory.getLogger(CaptchaAuthenticationProcessingFilter.class);
    public static final String SPRING_SECURITY_FORM_MOBILE_KEY = "phone";
    public static final String SPRING_SECURITY_FORM_CODE_KEY = "code";
    private static final String LOGIN_METHOD = "POST";

    private String mobileParameter = SPRING_SECURITY_FORM_MOBILE_KEY;
    private String codeParameter = SPRING_SECURITY_FORM_CODE_KEY;
    private boolean postOnly = true;

    public CaptchaAuthenticationProcessingFilter(@Lazy AuthenticationManager manager) {
        super(new AntPathRequestMatcher("/login/captcha", LOGIN_METHOD));
        this.setAuthenticationManager(manager);
        this.setAuthenticationSuccessHandler(new SuccessHandler());
        this.setAuthenticationFailureHandler(new FailureHandler());
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        log.debug("验证码登录过滤器");
        String phone = obtainPhone(request);
        String code = obtainCode(request);
        if (postOnly && !request.getMethod().endsWith(LOGIN_METHOD)) {
            throw new AuthenticationServiceException(
                    "Authentication method not supported: " + request.getMethod());
        }

        if (phone == null) {
            phone = "";
        }

        if (code == null) {
            code = "";
        }

        phone = phone.trim();

        CaptchaProviderToken tokenRequest = new CaptchaProviderToken(phone, code);

        setDetails(request, tokenRequest);

        return this.getAuthenticationManager().authenticate(tokenRequest);

    }

    protected void setDetails(HttpServletRequest request,
                              CaptchaProviderToken tokenRequest) {
        tokenRequest.setDetails(authenticationDetailsSource.buildDetails(request));
    }


    protected String obtainCode(HttpServletRequest request) {
        return request.getParameter(codeParameter);
    }

    protected String obtainPhone(HttpServletRequest request) {
        return request.getParameter(mobileParameter);
    }

    public void setMobileParameter(String mobileParameter) {
        Assert.hasText(mobileParameter, "Username parameter must not be empty or null");
        this.mobileParameter = mobileParameter;
    }

    public void setCodeParameter(String codeParameter) {
        Assert.hasText(codeParameter, "Password parameter must not be empty or null");
        this.codeParameter = codeParameter;
    }

    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }

    public final String getMobileParameter() {
        return mobileParameter;
    }

    public final String getCodeParameter() {
        return codeParameter;
    }

}
